package assdraw2.canvas;

import java.awt.Color;
import java.util.Vector;

import assdraw2.canvas.abstraction.CanvasAbstraction;
import assdraw2.canvas.abstraction.CanvasShapeModel;
import assdraw2.canvas.abstraction.Selection;
import assdraw2.canvas.abstraction.Shape;
import assdraw2.canvas.abstraction.command.AddCommand;
import assdraw2.canvas.abstraction.event.DrawingEvent;
import assdraw2.canvas.abstraction.event.DrawingListener;
import assdraw2.canvas.presentation.CanvasPresentation;
import assdraw2.common.MessageType;
import assdraw2.common.PACAgent;
import assdraw2.common.PACMessage;

public class CanvasControl implements PACAgent, DrawingListener {

	private CanvasAbstraction abstraction = new CanvasAbstraction(
			new CanvasShapeModel(400, 400), new Selection());
	private CanvasPresentation presentation;
	private PACAgent parent;
	
	private int oldMouseX;
	private int oldMouseY;

	public CanvasControl(PACAgent parent) {
		super();
		this.parent = parent;
	}

	@Override
	public void receiveMessage(PACMessage m) {
		if (m.getType() == MessageType.OPEN) {
			presentation = new CanvasPresentation(this, abstraction
					.getShapeModel());
			getShapeModel().addDrawingListener(this);
			
		} else if (m.getType() == MessageType.CLOSE) {
			getShapeModel().removeDrawingListener(this);
			presentation.dispose();

		} else if (m.getType() == MessageType.COLOR) {
			abstraction.setCurrentColor((Color) m.getContent());
		} else if (m.getType() == MessageType.TOOL) {
			abstraction.setCurrentCommand((AddCommand) (m.getContent()));
		} else if (m.getType() == MessageType.SHAPE_GROUP) {
			abstraction.getShapeModel().group(abstraction.getSlection());
		} else if (m.getType() == MessageType.SHAPE_UNGROUP) {
			for (Shape s : abstraction.getSlection()) {
				abstraction.getShapeModel().ungroup(s);
			}
			abstraction.getSlection().clear();
		} else if (m.getType() == MessageType.SIZE_UP) {
			for (Shape s : getSelection())
				s.scale(1.1, 1.1);
			presentation.repaint();
		} else if (m.getType() == MessageType.SIZE_DOWN) {
			for (Shape s : getSelection())
				s.scale(0.9, 0.9);
			presentation.repaint();
		} else if (m.getType() == MessageType.ZOOM_IN) {
			presentation.zoomIn();
		} else if (m.getType() == MessageType.ZOOM_OUT) {
			presentation.zoomOut();
		}

	}

	@Override
	public void sendMessage(PACMessage m) {
		if (m.getType() == MessageType.TOOL
				|| m.getType() == MessageType.SHAPE_ADDED
				|| m.getType() == MessageType.SHAPE_MOVED
				|| m.getType() == MessageType.SHAPE_DELETED
				|| m.getType() == MessageType.SHAPE_SELECTION) {
			parent.receiveMessage(m);
		} else if (m.getType() == MessageType.CLOSE) {
			getShapeModel().removeDrawingListener(this);
			parent.receiveMessage(m);
		}
	}
	
	public void mouseClicked(int x, int y){
		Vector<Shape> v = getShapeModel().getShapes();
    	for(int i=v.size()-1; i>=0; i--){
    		Shape s = v.get(i);
    		if(s.contains(x, y)){
    			if(!getSelection().contains(s)){
    				getSelection().add(s);

    				sendMessage(new PACMessage(MessageType.SHAPE_SELECTION, this, s));
    			}
    			presentation.repaint();
    			return;
    		}
    	}
    	
    	if(getSelection().isEmpty()){
    		getCommnad().execute(x, y, getShapeModel(), getColor());
    			    		
    	}else{
    		getSelection().clear();
    		//TODO - send message with shape to selection bar
    		presentation.repaint();
    	}
	}

    public void mousePressed(int x, int y)
    {
    	if(!getSelection().isEmpty()){
    		
    		for(Shape s : getSelection()){
    			if(s.contains(x, y)){
    				presentation.addMouseMotionListener(presentation);
    				oldMouseX = x;
    				oldMouseY = y;
    				break;
    			}
    		}
    		
    	}
    }
    
	public void mouseDragged(int x, int y) {

		for(Shape s : getSelection()){
			s.move(s.getX() + x - oldMouseX, s.getY() + y - oldMouseY);
		}
		oldMouseX = x;
		oldMouseY = y;
	}
	
	public CanvasShapeModel getShapeModel() {
		return abstraction.getShapeModel();
	}

	public Vector<Shape> getSelection() {
		return abstraction.getSlection();
	}

	public void setCanvasModel(CanvasShapeModel d) {
		abstraction.setCanvasModel(d);
	}

	public AddCommand getCommnad() {
		return abstraction.getCurrentCommand();
	}

	public Color getColor() {
		return abstraction.getCurrentColor();
	}

	public PACAgent getParentAgent() {
		return parent;
	}

	public void update(DrawingEvent e)
    {
    	if(e.getKind() == DrawingEvent.SHAPE_GROUP){
    		getSelection().clear();
    	}
    	
        presentation.repaint();
        	        
        MessageType t = null;
        if(e.getKind() == DrawingEvent.SHAPE_GROUP){
        	t = MessageType.SHAPE_GROUP;
        }else if(e.getKind() == DrawingEvent.SHAPE_ADDED){
        	t = MessageType.SHAPE_ADDED;
        }else if(e.getKind() == DrawingEvent.SHAPE_DELETED){
        	t = MessageType.SHAPE_DELETED;
        }else if(e.getKind() == DrawingEvent.SHAPE_UNGROUP){
        	t = MessageType.SHAPE_UNGROUP;
        }else if(e.getKind() == DrawingEvent.SHAPE_MOVED){
        	t = MessageType.SHAPE_MOVED;
        }else if(e.getKind() == DrawingEvent.SHAPE_SELECTION){
        	t = MessageType.SHAPE_SELECTION;
        }
        
        sendMessage(new PACMessage(t, this, e.getShape()));
    }

}
